package com.jeasonzhao.commons.utils;

import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class Algorithms
{
    public static final DecimalFormat DEFAULT_INTEGER_FORMAT = new DecimalFormat("############################");
    public static final DecimalFormat DEFAULT_DOUBLE_FORMAT = new DecimalFormat("############################.############################");
    public static final DecimalFormat DEFAULT_CURRENCY_FORMAT = new DecimalFormat("###########################0.##");
    public static final SimpleDateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static final String ChineseSymbols =
        "。；“”‘，｜、　—＠～！＃％…×（）＋＝｛｝【】《》"
        + "ａｂｃｄｅｆｇｈｉｊｋｌｍｎｏｐｑｒｓｔｕｖｗｘｙｚ"
        + "ＡＢＣＤＥＦＧＨＩＪＫＬＭＮＯＰＱＲＳＴＵＶＷＸＹＺ"
        + "１２３４５６７８９０．";
    private static net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat PingYing =
        new net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat();
    private static final java.util.Hashtable<String,String> CHSMAP = new java.util.Hashtable<String,String>();
    static
    {
        CHSMAP.put("。",".");
        CHSMAP.put("；",";");
        CHSMAP.put("“","\"");
        CHSMAP.put("”","\"");
        CHSMAP.put("‘","\'");
        CHSMAP.put("，",",");
        CHSMAP.put("｜","|");
        CHSMAP.put("、",".");
        CHSMAP.put("　"," ");
        CHSMAP.put("——","_");
        CHSMAP.put("＠","@");
        CHSMAP.put("～","~");
        CHSMAP.put("！","!");
        CHSMAP.put("＃","#");
        CHSMAP.put("％","%");
        CHSMAP.put("……","^");
        CHSMAP.put("×","*");
        CHSMAP.put("（","(");
        CHSMAP.put("）",")");
        CHSMAP.put("＋","+");
        CHSMAP.put("＝","=");
        CHSMAP.put("｛","{");
        CHSMAP.put("｝","}");
        CHSMAP.put("【","[");
        CHSMAP.put("】","]");
        CHSMAP.put("《","<");
        CHSMAP.put("》",">");
        CHSMAP.put("ａ","a");
        CHSMAP.put("ｂ","b");
        CHSMAP.put("ｃ","c");
        CHSMAP.put("ｄ","d");
        CHSMAP.put("ｅ","e");
        CHSMAP.put("ｆ","f");
        CHSMAP.put("ｇ","g");
        CHSMAP.put("ｈ","h");
        CHSMAP.put("ｉ","i");
        CHSMAP.put("ｊ","j");
        CHSMAP.put("ｋ","k");
        CHSMAP.put("ｌ","l");
        CHSMAP.put("ｍ","m");
        CHSMAP.put("ｎ","n");
        CHSMAP.put("ｏ","o");
        CHSMAP.put("ｐ","p");
        CHSMAP.put("ｑ","q");
        CHSMAP.put("ｒ","r");
        CHSMAP.put("ｓ","s");
        CHSMAP.put("ｔ","t");
        CHSMAP.put("ｕ","u");
        CHSMAP.put("ｖ","v");
        CHSMAP.put("ｗ","w");
        CHSMAP.put("ｘ","x");
        CHSMAP.put("ｙ","y");
        CHSMAP.put("ｚ","z");
        CHSMAP.put("Ａ","A");
        CHSMAP.put("Ｂ","B");
        CHSMAP.put("Ｃ","C");
        CHSMAP.put("Ｄ","D");
        CHSMAP.put("Ｅ","E");
        CHSMAP.put("Ｆ","F");
        CHSMAP.put("Ｇ","G");
        CHSMAP.put("Ｈ","H");
        CHSMAP.put("Ｉ","I");
        CHSMAP.put("Ｊ","J");
        CHSMAP.put("Ｋ","K");
        CHSMAP.put("Ｌ","L");
        CHSMAP.put("Ｍ","M");
        CHSMAP.put("Ｎ","N");
        CHSMAP.put("Ｏ","O");
        CHSMAP.put("Ｐ","P");
        CHSMAP.put("Ｑ","Q");
        CHSMAP.put("Ｒ","R");
        CHSMAP.put("Ｓ","S");
        CHSMAP.put("Ｔ","T");
        CHSMAP.put("Ｕ","U");
        CHSMAP.put("Ｖ","V");
        CHSMAP.put("Ｗ","W");
        CHSMAP.put("Ｘ","X");
        CHSMAP.put("Ｙ","Y");
        CHSMAP.put("Ｚ","Z");
        CHSMAP.put("１","1");
        CHSMAP.put("２","2");
        CHSMAP.put("３","3");
        CHSMAP.put("４","4");
        CHSMAP.put("５","5");
        CHSMAP.put("６","6");
        CHSMAP.put("７","7");
        CHSMAP.put("８","8");
        CHSMAP.put("９","9");
        CHSMAP.put("０","0");
        CHSMAP.put("．",".");
        PingYing.setCaseType(net.sourceforge.pinyin4j.format.HanyuPinyinCaseType.LOWERCASE);
        PingYing.setVCharType(net.sourceforge.pinyin4j.format.HanyuPinyinVCharType.WITH_U_AND_COLON);
        PingYing.setToneType(net.sourceforge.pinyin4j.format.HanyuPinyinToneType.WITHOUT_TONE);

    }

    private Algorithms()
    {
    }

    /////////////////////////////Normal operations//////////////////////////////////////////
    public static final boolean notEmpty(Object obj)
    {
        return false == isEmpty(obj);
    }

    public static final boolean isEmpty(Object obj)
    {
        if(null == obj)
        {
            return true;
        }
        else
        {
            if(obj instanceof String
               || obj instanceof StringBuilder
               || obj instanceof StringBuffer
               || obj instanceof java.io.StringWriter
                )
            {
                return obj.toString().trim().length() < 1;
            }
            else
            {
                return false;
            }
        }
    }

    ////////////////////////////////Chinese functionalities////////////////////////////////////////


    public static String toASCIICharSet(String str)
    {
        if(str == null)
        {
            return null;
        }
        String strRet = str;
        java.util.Enumeration<String> er = CHSMAP.keys();
        while(er.hasMoreElements())
        {
            String strK = (String) er.nextElement();
            String strV = (String) CHSMAP.get(strK);
            if(strK.equals(strV))
            {
                continue;
            }
            strRet = strRet.replaceAll(strK,strV);
        }
        return strRet;
    }

    public static final String repeatString(String string,int repeatCount)
    {

        if(null == string)
        {
            return null;
        }
        else if(string.length() < 1)
        {
            return string;
        }
        else if(repeatCount <= 0)
        {
            return "";
        }
        else if(1 == repeatCount)
        {
            return string;
        }
        else
        {
            StringBuffer s = new StringBuffer();
            for(int n = 0;n < repeatCount;n++)
            {
                s.append(string);
            }
            return s.toString();
        }
    }

    public static final String removeChineseBlanks(String str)
    {
        return removeBlanks(toASCIICharSet(str));
    }

    public static final String removeBlanks(String str)
    {
        if(str == null)
        {
            return null;
        }
        else
        {
            return str.replaceAll("\\s","");
        }
    }

    public static final String replaceStringByPosition(String str,Object ...parameters)
    {
        if(null == str || str.length() < 1 || parameters == null || parameters.length < 1)
        {
            return str;
        }
        for(int n = 0;n < parameters.length;n++)
        {
            java.util.regex.Pattern p = java.util.regex.Pattern.compile("\\{\\s*" + n + "\\s*\\}");
            String strSest = null == parameters[n] ? "" : Algorithms.toString(parameters[n]);
            strSest = strSest.replaceAll("\\\\","\\\\\\\\");
            str = p.matcher(str).replaceAll(strSest);
        }
        return str;
    }

    public static final String replaceStringByName(String str,Object ...parameters)
    {
        if(null == str || str.length() < 1 || parameters == null || parameters.length < 1)
        {
            return str;
        }
        java.util.Hashtable<String,String> map = new java.util.Hashtable<String,String>();
        for(int n = 0;n < parameters.length && (n + 1) < parameters.length;n += 2)
        {
            String key = parameters[n] == null ? null : parameters[n].toString();
            if(isEmpty(key))
            {
                continue;
            }
            String value = parameters[n + 1] == null ? "" : parameters[n + 1].toString();
            key = key.trim();
            if(key.startsWith("${"))
            {
                key = key.substring(2);
            }
            if(key.endsWith("}"))
            {
                key = key.substring(0,key.length() - 1);
            }
            if(isEmpty(key))
            {
                continue;
            }
            //System.out.println(key.toLowerCase().trim()+"="+value);
            map.put(key.toLowerCase().trim(),value);
        }
        java.util.regex.Pattern p = java.util.regex.Pattern.compile("\\$\\{\\s*\\w+\\s*\\}");
        Matcher m = p.matcher(str);
        StringBuffer sbuf = new StringBuffer();
        while(m.find())
        {
            String key = m.group();
            key = key.trim();
            if(key.startsWith("${"))
            {
                key = key.substring(2);
            }
            if(key.endsWith("}"))
            {
                key = key.substring(0,key.length() - 1);
            }
            key = key.trim().toLowerCase();
            String value = map.get(key);
            if(null == value)
            {
                value = "[]";
            }
            //System.out.println(key+">>>"+value);
            m.appendReplacement(sbuf,value);
        }
        m.appendTail(sbuf);
        return sbuf.toString();
    }

    public static final String printf(String strFormat,Object ...objs)
    {
        java.io.StringWriter w = new java.io.StringWriter();
        java.io.PrintWriter pw = new java.io.PrintWriter(w,true);
        pw.printf(strFormat,objs);
        String str = w.toString();
        pw.close();
        try
        {
            w.close();
        }
        catch(IOException ex)
        {
        	ex.printStackTrace();
        }
        return str;
    }

    public static String padRight(String str,int nLength)
    {
        return padRight(str,nLength," ");
    }

    public static String padRight(String str,int nLength,char c)
    {
        return padRight(str,nLength,"" + c);
    }

    public static String padRight(String str,int nLength,String c)
    {
        if(null == str || nLength <= str.length() || c == null || c.length() < 1)
        {
            return str;
        }
        StringBuffer buf = new StringBuffer(str);
        while(buf.length() < nLength)
        {
            buf.append(c);
        }
        return buf.toString();
    }

    public static final String padLeftAndRight(String str,int nLength)
    {
        return padLeftAndRight(str,nLength," ");
    }

    public static final String padLeftAndRight(String str,int nLength,char c)
    {
        return padLeftAndRight(str,nLength,"" + c);
    }

    public static final String padLeftAndRight(String str,int nLength,String c)
    {
        if(null == str || c == null || c.length() < 1 || nLength <= str.length())
        {
            return str;
        }
        StringBuffer buf = new StringBuffer(str);
        while(buf.length() < nLength)
        {
            buf.insert(0,c);
            if(buf.length() < nLength)
            {
                buf.append(c);
            }
        }
        return buf.toString();
    }

    public static String padLeft(String str,int nLength,char c)
    {
        return padLeft(str,nLength,"" + c);
    }

    public static String padLeft(String str,int nLength,String c)
    {
        if(null == str || nLength <= str.length() || c == null || c.length() < 1)
        {
            return str;
        }
        while(str.length() < nLength)
        {
            str = c + str;
        }
        return str;
    }

    public static final String padLeft(String str,int nLength)
    {
        return padLeft(str,nLength,' ');
    }

    public static final <T> T[] removeNullItem(T[] ary)
    {
        if(null == ary || ary.length < 1)
        {
            return null;
        }
        java.util.List<T> list = new java.util.ArrayList<T>();
        Class<?> inittype = null;
        for(T t : ary)
        {
            if(notEmpty(t))
            {
                if(inittype == null)
                {
                    inittype = ((Object) t).getClass();
                }
                list.add(t);
            }
        }
        if(ary.length == list.size())
        {
            return ary;
        }
        else
        {
            @SuppressWarnings("unchecked")
            T[] newary = (T[]) java.lang.reflect.Array.newInstance(inittype,list.size());

            for(int n = 0;n < list.size();n++)
            {
                newary[n] = list.get(n);
            }
            return newary;
        }
    }

    public static final java.util.List<?> removeNullItem(java.util.List<?> coll)
    {
        if(null != coll)
        {
            for(int n = 0;n < coll.size();n++)
            {
                if(isEmpty(coll.get(n)))
                {
                    coll.remove(n);
                    n--;
                }
            }
        }
        return coll;
    }

    public static final Object[] toArray(Object value)
    {
        return toArray(value,true);
    }

    public static final Object[] toArray(Object value,boolean doesConvertCollection)
    {
        if(null == value)
        {
            return null;
        }
        Object[] ret = null;
        if(doesConvertCollection
           && java.util.Collection.class.isAssignableFrom(value.getClass()))
        {
            java.util.Collection<?> cxs = (java.util.Collection<?>) value;
            Object[] objs = new Object[cxs.size()];
            cxs.toArray(objs);
            ret = objs;
        }
        else if(java.util.Enumeration.class.isAssignableFrom(value.getClass()))
        {
            java.util.Enumeration<?> e = (java.util.Enumeration<?>) value;
            java.util.ArrayList<Object> r = new java.util.ArrayList<Object>();
            while(e.hasMoreElements())
            {
                r.add(e.nextElement());
            }
            Object[] objs = new Object[r.size()];
            r.toArray(objs);
            return objs;
        }
        else if(value.getClass().isArray())
        {
            Class<?> type = value.getClass().getComponentType();
            Object[] objs = null;
            if(type == Boolean.TYPE)
            {
                boolean[] bs = (boolean[]) value;
                objs = new Object[bs.length];
                for(int n = 0;n < bs.length;n++)
                {
                    objs[n] = Boolean.valueOf(bs[n]);
                }
            }
            else if(type == Byte.TYPE)
            {
                byte[] bs = (byte[]) value;
                objs = new Object[bs.length];
                for(int n = 0;n < bs.length;n++)
                {
                    objs[n] = Byte.valueOf(bs[n]);
                }
            }
            else if(type == Short.TYPE)
            {
                short[] bs = (short[]) value;
                objs = new Object[bs.length];
                for(int n = 0;n < bs.length;n++)
                {
                    objs[n] = Short.valueOf(bs[n]);
                }
            }
            else if(type == Integer.TYPE)
            {
                int[] bs = (int[]) value;
                objs = new Object[bs.length];
                for(int n = 0;n < bs.length;n++)
                {
                    objs[n] = Integer.valueOf(bs[n]);
                }
            }
            else if(type == Long.TYPE)
            {
                long[] bs = (long[]) value;
                objs = new Object[bs.length];
                for(int n = 0;n < bs.length;n++)
                {
                    objs[n] = Long.valueOf(bs[n]);
                }
            }
            else if(type == Float.TYPE)
            {
                float[] bs = (float[]) value;
                objs = new Object[bs.length];
                for(int n = 0;n < bs.length;n++)
                {
                    objs[n] = Float.valueOf(bs[n]);
                }
            }
            else if(type == Double.TYPE)
            {
                double[] bs = (double[]) value;
                objs = new Object[bs.length];
                for(int n = 0;n < bs.length;n++)
                {
                    objs[n] = Double.valueOf(bs[n]);
                }
            }
            else if(type == Character.TYPE)
            {
                char[] bs = (char[]) value;
                objs = new Object[bs.length];
                for(int n = 0;n < bs.length;n++)
                {
                    objs[n] = Character.valueOf(bs[n]);
                }
            }
            else
            {
                objs = (Object[]) value;
            }
            ret = objs;
        }
        return ret;
    }

    public static final String toString(Object value,String strFormat)
    {
        if(null == value)
        {
            return null;
        }
        DataTypes dt = DataTypes.from(value.getClass());
        if(dt.isArray())
        {
            return toString(toArray(value,true));
        }
        else if(dt.isDate())
        {
            SimpleDateFormat df = isEmpty(strFormat) ? DEFAULT_DATE_FORMAT : new SimpleDateFormat(strFormat);
            return df.format((Date) value);
        }
        else if(dt.isInteger())
        {
            DecimalFormat sf = isEmpty(strFormat) ? DEFAULT_INTEGER_FORMAT : new DecimalFormat(strFormat);
            return sf.format(value);
        }
        else if(dt.isDouble())
        {
            DecimalFormat sf = isEmpty(strFormat) ? DEFAULT_DOUBLE_FORMAT : new DecimalFormat(strFormat);
            return sf.format(value);
        }
        return value.toString();
    }

    public static final String toString(Object value)
    {
        return toString(value,null);
    }

    public static final String toString(java.lang.Iterable<?> coll)
    {
        return toString(coll,",",false);
    }

    public static final String toString(java.lang.Iterable<?> coll,String strSep)
    {
        return toString(coll,strSep,false);
    }

    public static final String toString(java.lang.Iterable<?> coll,String strSep,boolean isAppendAtHeader)
    {
        if(null == coll)
        {
            return "";
        }
        else
        {
            StringBuffer strRet = new StringBuffer();
            int n = 0;
            for(Object obj : coll)
            {
                if(false == isEmpty(strSep) &&
                   (n > 0 || isAppendAtHeader))
                {
                    strRet.append(strSep);
                }
                strRet.append(toString(obj));
                n++;
            }
            return strRet.toString();
        }
    }

    public static final String toString(Object[] coll)
    {
        return toString(coll,",",false);
    }

    public static final String toString(Object[] coll,String strSep)
    {
        return toString(coll,strSep,false);
    }

    public static final String toString(Object[] coll,String strSep,boolean isAppendAtHeader)
    {
        if(null == coll)
        {
            return "";
        }
        else
        {
            StringBuffer strRet = new StringBuffer();
            for(int n = 0;n < coll.length;n++)
            {
                if(false == isEmpty(strSep) &&
                   (n > 0 || isAppendAtHeader))
                {
                    strRet.append(strSep);
                }
                strRet.append(toString(coll[n]));
            }
            return strRet.toString();
        }
    }

    public static final String join(Object obj,String sep)
    {
        if(null == obj)
        {
            return null;
        }
        else if(DataTypes.isArray(obj.getClass()) == false)
        {
            return toString(obj);
        }
        else
        {
            StringBuffer buf = new StringBuffer();
            for(Object t : toArray(obj))
            {
                if(null != t)
                {
                    if(buf.length() > 0 && null != sep)
                    {
                        buf.append(sep);
                    }
                    buf.append(toString(t));
                }

            }
            return buf.toString();
        }
    }

    ///////////////////////////////COMPARE//////////////////////////////////////
    public static final boolean areEquals(Object firstValue,Object secondValue)
    {
        return areEquals((DataTypes)null,firstValue,secondValue);
    }

    public static final boolean areEquals(DataTypes comparingDataType,Object firstValue,Object secondValue)
    {
        return compare(comparingDataType,firstValue,secondValue) == 0;
    }

    public static final boolean areEquals(Class<?> comparingDataType,Object firstValue,Object secondValue)
    {
        return compare(comparingDataType,firstValue,secondValue) == 0;
    }

    public static final int compare(Object firstValue,Object secondValue)
    {
        return compare((DataTypes)null,firstValue,secondValue);
    }

    public static final int compare(Class<?> comparingDataType,Object firstValue,Object secondValue)
    {
        return compare(null == comparingDataType ? null : DataTypes.from(comparingDataType),firstValue,secondValue);
    }

    public static final int compare(DataTypes comparingDataType,Object firstValue,Object secondValue)
    {
        final int LessThan = -1,GreaterThan = 1,Equals = 0;
        if(null == firstValue || secondValue == null)
        {
            return firstValue == null && secondValue == null
                ? Equals : (secondValue == null ? GreaterThan : LessThan);
        }
        if(null == comparingDataType)
        {
            comparingDataType = DataTypes.from(firstValue.getClass());
        }
        if(comparingDataType.isArray())
        {
            Object[] firstArray = toArray(firstValue,true);
            Object[] secondArray = toArray(secondValue,true);
            if(firstArray == null || secondArray == null)
            {
                return null == firstArray && null == secondArray ? Equals :
                    (firstArray == null ? LessThan : GreaterThan);
            }
            for(int nIdx = 0;null != firstArray
                && null != secondArray
                && nIdx < firstArray.length && nIdx < secondArray.length
                ;nIdx++)
            {
                Object firstItem = firstArray[nIdx];
                Object secondItem = secondArray[nIdx];
                int tempResult = Equals;
                if(null == firstItem || null == secondItem)
                {
                    tempResult = firstItem == null ? LessThan : GreaterThan;
                }
                else
                {
                    tempResult = compare(DataTypes.from(
                        null == firstValue.getClass().getComponentType() ? firstItem.getClass()
                        : firstValue.getClass().getComponentType())
                                         ,firstItem,secondItem);
                }
                if(tempResult != Equals)
                {
                    return tempResult;
                }
            }
            return firstArray.length == secondArray.length ? Equals
                : (firstArray.length < secondArray.length ? LessThan : GreaterThan);
        }
        else if(comparingDataType.isDate())
        {
            int tempResult = ConvertEx.toDate(firstValue).compareTo(ConvertEx.toDate(secondValue));
            return tempResult == 0 ? Equals : (tempResult < 0 ? LessThan : GreaterThan);
        }
        else if(comparingDataType.isNumeric())
        {
            double firstDouble = ConvertEx.toDouble(firstValue);
            double secondDouble = ConvertEx.toDouble(secondValue);
            return firstDouble == secondDouble ? Equals : (firstDouble < secondDouble ? LessThan : GreaterThan);
        }
        else
        {
            String f = toString(firstValue);
            String s = toString(secondValue);
            int tempResult = f.compareTo(s);
            return tempResult == 0 ? Equals : (tempResult < 0 ? LessThan : GreaterThan);
        }
    }

    public static final Object castValueSafe(Class<?> cls,Object obj)
    {
        try
        {
            return castValue(cls,obj);
        }
        catch(Exception excep)
        {
            return obj;
        }
    }

    public static final Object castValueSafe(DataTypes t,Object obj)
    {
        try
        {
            return castValue(t,obj);
        }
        catch(Exception excep)
        {
            return obj;
        }
    }

    public static final Object castValue(Class<?> cls,Object obj)
    {
        return castValue(DataTypes.from(cls),obj);
    }

    @SuppressWarnings("unchecked")
    public static final <T extends Enum<?>> T enumFrom(Class<T> cls,int n)
    {
        if(null == cls)
        {
            return null;
        }
        else
        {
            for(Enum<?> e : cls.getEnumConstants())
            {
                if(e.ordinal() == n)
                {
                    return(T) e;
                }
            }
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    public static final <T extends Enum<?>> T enumFrom(Class<T> cls,String name)
    {
        if(null == cls || null == name)
        {
            return null;
        }
        else
        {
            for(Enum<?> e : cls.getEnumConstants())
            {
                if(e.name().equalsIgnoreCase(name.trim()))
                {
                    return(T) e;
                }
            }
            return enumFrom(cls,ConvertEx.toInt(name, -999999));
        }
    }

    @SuppressWarnings(
        {"unchecked","rawtypes"})
    public static final Object castValue(DataTypes targetDataType,Object originalValue)
    {
        if(null == targetDataType)
        {
            return originalValue;
        }
        else if(null != originalValue
                && targetDataType.getInitType().equals(originalValue.getClass()))
        {
            return originalValue;
        }
        else if(targetDataType.getInitType() != null
                && targetDataType.getInitType().isEnum()
                && null != originalValue)
        {
            if(ConvertEx.isInt(originalValue))
            {
                return enumFrom((Class) targetDataType.getInitType(),ConvertEx.toInt(originalValue));
            }
            else
            {
                return enumFrom((Class) targetDataType.getInitType(),originalValue.toString());
            }
        }
        else if(null == originalValue
                || (targetDataType.equals(DataTypes.OBJECT)
                    && targetDataType.getInitType().equals(Object.class)))
        {
            return originalValue;
        }
        else if(targetDataType.isArray())
        {
            Object[] ary = toArray(originalValue,true);
            if(targetDataType.getInitType().isArray())
            {
                if(null == targetDataType.getComponentType() || Object.class.equals(targetDataType.getComponentType()) || null == ary)
                {
                    return ary;
                }
                DataTypes dtc = DataTypes.from(targetDataType.getComponentType());
                Object aryret = java.lang.reflect.Array.newInstance(targetDataType.getComponentType(),ary.length);
                for(int n = 0;null != ary && n < ary.length;n++)
                {
                    java.lang.reflect.Array.set(aryret,n,castValue(dtc,ary[n]));
                }
                return aryret;
            }
            else
            {
                java.util.Collection<Object> aryet = new java.util.ArrayList<Object>();
                if(java.util.Vector.class.isAssignableFrom(targetDataType.getInitType()))
                {
                    aryet = new java.util.Vector<Object>();
                }
                for(int n = 0;null != ary && n < ary.length;n++)
                {
                    aryet.add(ary[n]);
                }
                return aryet;
            }
        }
        else if(targetDataType.getInitType() == Boolean.TYPE
                || Boolean.class.isAssignableFrom(targetDataType.getInitType()))
        {
            return ConvertEx.toBoolean(originalValue);
        }
        else if(targetDataType.getInitType() == Byte.TYPE
                || Byte.class.isAssignableFrom(targetDataType.getInitType()))
        {
            return Byte.valueOf((byte) ConvertEx.toInt(originalValue));
        }
        else if(targetDataType.getInitType() == Short.TYPE
                || Short.class.isAssignableFrom(targetDataType.getInitType()))
        {
            return Short.valueOf((short) ConvertEx.toInt(originalValue));
        }
        else if(targetDataType.getInitType() == Integer.TYPE
                || Integer.class.isAssignableFrom(targetDataType.getInitType()))
        {
            return ConvertEx.toInteger(originalValue);
        }
        else if(targetDataType.getInitType() == Long.TYPE
                || Long.class.isAssignableFrom(targetDataType.getInitType()))
        {
            return Long.valueOf(ConvertEx.toInt(originalValue));
        }
        else if(targetDataType.getInitType() == Float.TYPE
                || Float.class.isAssignableFrom(targetDataType.getInitType()))
        {
            return Float.valueOf((float) ConvertEx.toDouble(originalValue));
        }
        else if(targetDataType.getInitType() == Double.TYPE
                || Double.class.isAssignableFrom(targetDataType.getInitType()))
        {
            return Double.valueOf(ConvertEx.toDouble(originalValue));
        }
        else if(targetDataType.getInitType() == Character.TYPE
                || Character.class.isAssignableFrom(targetDataType.getInitType()))
        {
            return Character.valueOf((char) ConvertEx.toInt(originalValue));
        }
        else if(targetDataType.equals(DataTypes.INT))
        {
            return ConvertEx.toInteger(originalValue);
        }
        else if(targetDataType.equals(DataTypes.DOUBLE))
        {
            return ConvertEx.toDoubleObject(originalValue);
        }
        else if(targetDataType.equals(DataTypes.STRING))
        {
            return originalValue.toString();
        }
        else if(targetDataType.equals(DataTypes.BOOL))
        {
            return ConvertEx.toBoolean(originalValue);
        }
        else if(targetDataType.equals(DataTypes.DATE))
        {
            java.util.Date d = ConvertEx.toDate(originalValue);
            if(targetDataType.getInitType().equals(java.sql.Date.class))
            {
                return new java.sql.Date(d.getTime());
            }
            else if(targetDataType.getInitType().equals(java.sql.Time.class))
            {
                return new java.sql.Time(d.getTime());
            }
            else if(targetDataType.getInitType().equals(java.sql.Timestamp.class))
            {
                return new java.sql.Timestamp(d.getTime());
            }
            else
            {
                return d;
            }
        }
        else
        {
            return originalValue;
        }
    }

    private static final String REGEX_XMLVALIDATOR = "^\\s*((<\\w+[^>]*>.*?<[/]?\\w+[^>]*>)|(<[/]?\\w+[^>]*>))\\s*$";
    public static final boolean isXmlString(String x)
    {
        if(isEmpty(x))
        {
            return false;
        }
        else
        {
            java.util.regex.Pattern p = java.util.regex.Pattern.compile(REGEX_XMLVALIDATOR);
            return p.matcher(x.replaceAll("\\s+"," ")).find();
        }
    }

    public static final boolean isJSONString(String x)
    {
        if(isEmpty(x))
        {
            return false;
        }
        else
        {
            x = x.trim();
            return(x.startsWith("[") && x.endsWith("]"))
                || (x.startsWith("{") && x.endsWith("}"));
        }
    }

    private static final String REGEX_NAME = "^\\s*(([\u4e00-\u9fa5]|\\w|_)[\\w_\\d[\u4e00-\u9fa5]]+)|(([\u4e00-\u9fa5]|\\w)+)\\s*$";
    public static boolean isValidateSymbolName(String strVariableName)
    {
        return java.util.regex.Pattern.matches(REGEX_NAME,strVariableName);
    }

    public final static <T> T nvl(T ...parameters)
    {
        return oneOfNotNull(parameters);
    }

    public final static <T> T oneOfNotNull(T ...parameters)
    {
        if(null == parameters)
        {
            return null;
        }
        else
        {
            for(T t : parameters)
            {
                if(notEmpty(t))
                {
                    return t;
                }
            }
        }
        return null;
    }

    public final static String nvl(String ...parameters)
    {
        return oneOfNotNull(parameters);
    }

    public final static String oneOfNotNull(String ...parameters)
    {
        if(null == parameters)
        {
            return null;
        }
        else
        {
            for(String t : parameters)
            {
                if(notEmpty(t))
                {
                    return t;
                }
            }
        }
        return null;
    }

    public final static boolean isChinese(char c)
    {
        return Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS;
    }

    public static final boolean containsChinese(String strInput)
    {
        if(null == strInput || strInput.length() < 1)
        {
            return false;
        }
        else
        {
            String strRegex1 = "(?ms)(?i)^.*[\\u4e00-\\u9fbb]+.*$";
            String strRegex2 = "(?ms)(?i)^.*[" + ChineseSymbols + "]+.*$";
            Pattern p1 = Pattern.compile(strRegex1);
            Pattern p2 = Pattern.compile(strRegex2);
            return p1.matcher(strInput).matches() || p2.matcher(strInput).matches();
//            for(char c : strInput.toCharArray())
//            {
//                if(isChinese(c))
//                {
//                    return true;
//                }
//            }
//            return false;
        }
    }

    public final static String toPinYin(String str)
    {
        return toPinYin(str,true,false);
    }

    public final static String toPinYin(String str,boolean addBlank)
    {
        return toPinYin(str,addBlank,false);
    }

    public final static String toPinYin(String str,boolean addBlank,boolean onlychs)
    {
        if(null == str || str.trim().length() < 1)
        {
            return str;
        }
        StringBuffer ret = new StringBuffer();
        for(char c : str.toCharArray())
        {
            if(isChinese(c))
            {
                ret.append(toPinYin(c));
                if(addBlank)
                {
                    ret.append(' ');
                }
            }
            else
            {
                if(onlychs == false)
                {
                    ret.append(c);
                }
            }
        }
        return ret.toString();
    }

    public final static String toCaptialPinYin(String str)
    {
        return toCaptialPinYin(str,false);
    }

    public final static String toCaptialPinYin(String str,boolean onlychs)
    {
        if(null == str || str.trim().length() < 1)
        {
            return str;
        }
        StringBuffer ret = new StringBuffer();
        for(char c : str.toCharArray())
        {
            if(isChinese(c))
            {
                String p = toPinYin(c);
                if(p.trim().length() > 0)
                {
                    ret.append(p.trim().charAt(0));
                }
            }
            else
            {
                if(onlychs == false)
                {
                    ret.append(c);
                }
            }
        }
        return ret.toString().toUpperCase();
    }

    public final static String toPinYin(char c)
    {
        if(isChinese(c))
        {
            try
            {
                String[] ary = net.sourceforge.pinyin4j.PinyinHelper.toHanyuPinyinStringArray(c,PingYing);
                if(null != ary && ary.length > 0)
                {
                    return ary[0];
                }
            }
            catch(Exception ex)
            {
            	ex.printStackTrace();
            }
        }
        return "" + c;
    }

    public final static String trimEx(String str)
    {
        return null == str || str.trim().length() < 1 ? null : str.trim();
    }

    private static final char[] HEXDIGITS =
        {'0','1','2','3','4','5','6','7','8','9',
        'A','B','C','D','E','F'};
    public final static String hexString(byte ib)
    {
        char[] ob = new char[2];
        ob[0] = HEXDIGITS[(ib >>> 4) & 0X0F];
        ob[1] = HEXDIGITS[ib & 0X0F];
        String s = new String(ob);
        return s;
    }

    public static String hexString(byte[] bytes)
    {
        return hexString(bytes,false);
    }

    public static String hexString(byte[] bytes,boolean contansSpace)
    {
        if(null == bytes)
        {
            return null;
        }
        else
        {
            StringBuffer buf = new StringBuffer();
            for(int n = 0;null != bytes && n < bytes.length;n++)
            {
                if(n > 0 && contansSpace)
                {
                    buf.append(' ');
                }
                buf.append(hexString(bytes[n]));
            }
            return buf.toString();
        }
    }

    public static final <T> T[] sliceArray(T[] ary,int nstart,int nlength)
    {
        if(null == ary)
        {
            return null;
        }
        else if(nstart >= ary.length)
        {
            return null;
        }
        Class<?> componentType = ary.getClass().getComponentType();
        nstart = Math.max(nstart,0);
        if(nlength < 0 || nlength > (ary.length - nstart))
        {
            nlength = ary.length - nstart;
        }
        @SuppressWarnings("unchecked")
        T[] result = (T[]) java.lang.reflect.Array.newInstance(componentType,nlength);

        for(int n = 0;n < nlength;n++)
        {
            result[n] = ary[n + nstart];
        }
        return result;
    }

    public static final byte[] sliceArray(byte[] ary,int nstart,int nlength)
    {
        if(null == ary)
        {
            return null;
        }
        else if(nstart >= ary.length)
        {
            return null;
        }
        nstart = Math.max(nstart,0);
        if(nlength < 0 || nlength > (ary.length - nstart))
        {
            nlength = ary.length - nstart;
        }
        byte[] result = new byte[nlength];
        for(int n = 0;n < nlength;n++)
        {
            result[n] = ary[n + nstart];
        }
        return result;
    }

    public static final String[] sliceArray(String[] ary,int nstart,int nlength)
    {
        if(null == ary)
        {
            return null;
        }
        else if(nstart >= ary.length)
        {
            return null;
        }
        nstart = Math.max(nstart,0);
        if(nlength < 0 || nlength > (ary.length - nstart))
        {
            nlength = ary.length - nstart;
        }
        String[] result = new String[nlength];
        for(int n = 0;n < nlength;n++)
        {
            result[n] = ary[n + nstart];
        }
        return result;
    }

    public static final long[] sliceArray(long[] ary,int nstart,int nlength)
    {
        if(null == ary)
        {
            return null;
        }
        else if(nstart >= ary.length)
        {
            return null;
        }
        nstart = Math.max(nstart,0);
        if(nlength < 0 || nlength > (ary.length - nstart))
        {
            nlength = ary.length - nstart;
        }
        long[] result = new long[nlength];
        for(int n = 0;n < nlength;n++)
        {
            result[n] = ary[n + nstart];
        }
        return result;
    }

    public static final int[] sliceArray(int[] ary,int nstart,int nlength)
    {
        if(null == ary)
        {
            return null;
        }
        else if(nstart >= ary.length)
        {
            return null;
        }
        nstart = Math.max(nstart,0);
        if(nlength < 0 || nlength > (ary.length - nstart))
        {
            nlength = ary.length - nstart;
        }
        int[] result = new int[nlength];
        for(int n = 0;n < nlength;n++)
        {
            result[n] = ary[n + nstart];
        }
        return result;
    }

    public static final double[] sliceArray(double[] ary,int nstart,int nlength)
    {
        if(null == ary)
        {
            return null;
        }
        else if(nstart >= ary.length)
        {
            return null;
        }
        nstart = Math.max(nstart,0);
        if(nlength < 0 || nlength > (ary.length - nstart))
        {
            nlength = ary.length - nstart;
        }
        double[] result = new double[nlength];
        for(int n = 0;n < nlength;n++)
        {
            result[n] = ary[n + nstart];
        }
        return result;
    }

    public static final <T> T[] mergeArray(T[] ...arrays)
    {
        if(null == arrays)
        {
            return null;
        }
        Class<?> componentType = arrays.getClass().getComponentType().getComponentType();
        int length = 0;
        for(T[] t : arrays)
        {
            length += t == null ? 0 : t.length;
        }
        @SuppressWarnings("unchecked")
        T[] result = (T[]) java.lang.reflect.Array.newInstance(componentType,length);

        length = 0;
        for(T[] t : arrays)
        {
            if(null == t || t.length < 1)
            {
                continue;
            }
            System.arraycopy(t,0,result,length,t.length);
            length += t.length;
        }
        return result;
    }

    public static String[] mergeArray(String[] ...arrays)
    {
        if(null == arrays)
        {
            return null;
        }
        int length = 0;
        for(String[] array : arrays)
        {
            length += array.length;
        }
        String[] result = new String[length];
        length = 0;
        for(String[] array : arrays)
        {
            System.arraycopy(array,0,result,length,array.length);
            length += array.length;
        }
        return result;
    }

    public static byte[] mergeArray(byte[] ...arrays)
    {
        if(null == arrays)
        {
            return null;
        }
        int length = 0;
        for(byte[] array : arrays)
        {
            length += array.length;
        }
        byte[] result = new byte[length];
        length = 0;
        for(byte[] array : arrays)
        {
            System.arraycopy(array,0,result,length,array.length);
            length += array.length;
        }
        return result;
    }

    public static char[] mergeArray(char[] ...arrays)
    {
        if(null == arrays)
        {
            return null;
        }
        int length = 0;
        for(char[] array : arrays)
        {
            length += array.length;
        }
        char[] result = new char[length];
        length = 0;
        for(char[] array : arrays)
        {
            System.arraycopy(array,0,result,length,array.length);
            length += array.length;
        }
        return result;
    }

    public static short[] mergeArray(short[] ...arrays)
    {
        if(null == arrays)
        {
            return null;
        }
        int length = 0;
        for(short[] array : arrays)
        {
            length += array.length;
        }
        short[] result = new short[length];
        length = 0;
        for(short[] array : arrays)
        {
            System.arraycopy(array,0,result,length,array.length);
            length += array.length;
        }
        return result;
    }

    public static int[] mergeArray(int[] ...arrays)
    {
        if(null == arrays)
        {
            return null;
        }
        int length = 0;
        for(int[] array : arrays)
        {
            length += array.length;
        }
        int[] result = new int[length];
        length = 0;
        for(int[] array : arrays)
        {
            System.arraycopy(array,0,result,length,array.length);
            length += array.length;
        }
        return result;
    }

    public static long[] mergeArray(long[] ...arrays)
    {
        if(null == arrays)
        {
            return null;
        }
        int length = 0;
        for(long[] array : arrays)
        {
            length += array.length;
        }
        long[] result = new long[length];
        length = 0;
        for(long[] array : arrays)
        {
            System.arraycopy(array,0,result,length,array.length);
            length += array.length;
        }
        return result;
    }

    public static float[] mergeArray(float[] ...arrays)
    {
        if(null == arrays)
        {
            return null;
        }
        int length = 0;
        for(float[] array : arrays)
        {
            length += array.length;
        }
        float[] result = new float[length];
        length = 0;
        for(float[] array : arrays)
        {
            System.arraycopy(array,0,result,length,array.length);
            length += array.length;
        }
        return result;
    }

    public static double[] mergeArray(double[] ...arrays)
    {
        if(null == arrays)
        {
            return null;
        }
        int length = 0;
        for(double[] array : arrays)
        {
            length += array.length;
        }
        double[] result = new double[length];
        length = 0;
        for(double[] array : arrays)
        {
            System.arraycopy(array,0,result,length,array.length);
            length += array.length;
        }
        return result;
    }

    public static boolean[] mergeArray(boolean[] ...arrays)
    {
        if(null == arrays)
        {
            return null;
        }
        int length = 0;
        for(boolean[] array : arrays)
        {
            length += array.length;
        }
        boolean[] result = new boolean[length];
        length = 0;
        for(boolean[] array : arrays)
        {
            System.arraycopy(array,0,result,length,array.length);
            length += array.length;
        }
        return result;
    }
}
